home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #1 / Amiga Plus CD - 2000 - No. 1.iso / Tools / Dev / Meshwriter / reflections.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-03  |  14.2 KB  |  476 lines

  1. /*
  2. **      $VER: reflections.c 1.00 (27.03.1999)
  3. **
  4. **      Creation date : 02.01.1999
  5. **
  6. **      Description       :
  7. **         Standart saver module for meshwriter.library.
  8. **         Saves the mesh as Reflections file.
  9. **
  10. **
  11. **      Written by Stephan Bielmann
  12. **
  13. */
  14.  
  15. /*************************** Includes *******************************/
  16.  
  17. /*
  18. ** Amiga includes
  19. */
  20.  
  21. #include <clib/dos_protos.h>
  22.  
  23. /*
  24. ** Project includes
  25. */
  26. #include "meshwriter_private.h"
  27. #include "utilities.h"
  28.  
  29. /**************************** Defines *******************************/
  30.  
  31. /*
  32. ** Number of elements in the buffers
  33. */
  34. #define Ci_BUFFERS 100    // constant buffer size
  35.  
  36. /*********************** Type definitions ***************************/
  37.  
  38. /*
  39. ** Private type definitions
  40. */
  41. typedef struct {
  42.     FLOAT x,y,z;
  43. } REFVector;
  44.  
  45. typedef struct {
  46.     ULONG p,q,r;
  47. } REFTriangle;
  48.  
  49. typedef struct {
  50.     UBYTE name[4];
  51.     ULONG size;
  52. } REFChunk;
  53.  
  54. typedef struct {
  55.     REFChunk chunk;
  56.     UWORD version,revision;
  57.     ULONG nobjects,chksumpt,chksumobj;
  58. } REFInfoChunk;
  59.  
  60. typedef struct {
  61.     REFChunk chunk;
  62.     UWORD len;
  63. } REFRobjChunk;
  64.  
  65. typedef struct {
  66.     REFChunk chunk;
  67.     REFVector ursprung,x,y,z;
  68.     FLOAT size;
  69. } REFKsysChunk;
  70.  
  71. typedef struct {
  72.     REFChunk chunk;
  73.     ULONG npoints;
  74. } REFPktmChunk;
  75.  
  76. typedef struct {
  77.     REFChunk chunk;
  78.     ULONG dx,dy;
  79. } REFRpicChunk;
  80.  
  81. /********************** Private functions ***************************/
  82.  
  83. /********************** Public functions ****************************/
  84.  
  85. /********************************************************************\
  86. *                                                                    *
  87. * Name         : write3REF4                                          *
  88. *                                                                    *
  89. * Description  : Writes a standart reflections 4.X binary file.      *
  90. *                Revision 9 dated : 01.09.1996                       *
  91. *                                                                    *
  92. * Arguments    : reffile  IN : An already opened file stream.        *
  93. *                mesh     IN : Pointer to the mesh.                  *
  94. *                                                                    *
  95. * Return Value : RCNOERROR                                           *
  96. *                RCWRITEDATA                                         *
  97. *                                                                    *
  98. * Comment      : No default material.                                *
  99. *                                                                    *
  100. \********************************************************************/
  101. ULONG write3REF4(BPTR reffile, TOCLMesh *mesh) {
  102.     REFChunk            form,dre2,rge1,gma1,sur1;
  103.     REFInfoChunk        info;
  104.     REFRobjChunk        robj;
  105.     REFKsysChunk        ksys;
  106.     REFPktmChunk        pktm;
  107.     REFRpicChunk        rpic;
  108.     
  109.     TOCLPolygonNode            *pln=NULL;
  110.     TOCLVertexNode                *ver=NULL;
  111.     TOCLPolygonsVerticesNode    *plvi=NULL,*plv1=NULL,*plv2=NULL,*plv3=NULL;
  112.     TOCLMaterialNode            *mat=NULL;    
  113.  
  114.     ULONG                ndrei,nmatbodies,nmattriangles,smaterialnames;
  115.     REFVector            vbuffer[Ci_BUFFERS];    // Ci_BUFFERS * sizeof(REFVector)        vector buffer
  116.     REFTriangle        tbuffer[Ci_BUFFERS];    // Ci_BUFFERS * sizeof(REFTriangle)    triangle buffer
  117.     ULONG                lbuffer[Ci_BUFFERS];    // Ci_BUFFERS * sizeof(ULONG)            ulong buffer, for material triangles
  118.     UBYTE                bbuffer[Ci_BUFFERS];    // Ci_BUFFERS * sizeof(UBYTE)            ubyte buffer, for triangle flags
  119.     ULONG                bufferstate;
  120.     ULONG                 i,l;
  121.     // constant glanzkurve including count
  122.     UBYTE glanz[]= {
  123.         0x00,0x00,0x00,0x0D,
  124.         0x3F,0x80,0x00,0x00,
  125.         0x3F,0x73,0x33,0x33,
  126.         0x3F,0x66,0x66,0x66,
  127.         0x3F,0x4C,0xCC,0xCD,
  128.         0x3F,0x19,0x99,0x9A,
  129.         0x3E,0x99,0x99,0x9A,
  130.         0x00,0x00,0x00,0x00,
  131.         0x00,0x00,0x00,0x00,
  132.         0x00,0x00,0x00,0x00,
  133.         0x00,0x00,0x00,0x00,
  134.         0x00,0x00,0x00,0x00,
  135.         0x00,0x00,0x00,0x00,
  136.         0x00,0x00,0x00,0x00
  137.     };
  138.  
  139.     
  140.     /*
  141.     ** Initializing all chunks and theyr sizes and static contents
  142.     */
  143.     setUBYTEArray(ksys.chunk.name,"KSYS",4);
  144.     ksys.chunk.size=52;                // fixed size
  145.     ksys.ursprung.x=0;                    // fixed origin to {0,0,0}
  146.     ksys.ursprung.y=0;
  147.     ksys.ursprung.z=0;
  148.     ksys.x.x=1,ksys.x.y=0,ksys.x.z=0;    // fixed x-unitvector
  149.     ksys.y.x=0,ksys.y.y=1,ksys.y.z=0;    // fixed y-unitvector
  150.     ksys.z.x=0,ksys.z.y=0,ksys.z.z=1;    // fixed z-unitvector
  151.     ksys.size=1;                            // fixed to 1, scale factor
  152.  
  153.     setUBYTEArray(pktm.chunk.name,"PKTM",4);
  154.     pktm.chunk.size=sizeof(pktm.chunk.size) + mesh->vertices.numberOfVertices * sizeof(REFVector);
  155.     pktm.npoints=mesh->vertices.numberOfVertices;
  156.  
  157.     // this chunk will be used twice, for the object and his materials at the end
  158.     setUBYTEArray(robj.chunk.name,"ROBJ",4);
  159.     robj.len=stringlen(mesh->name);
  160.     // size = 2 for the len field and the len value itselfs
  161.     robj.chunk.size=2+robj.len;
  162.  
  163.     setUBYTEArray(rge1.name,"RGE1",4);
  164.     // size = sizes of all chunk above and theyr size themselves = 8 for each one
  165.     // and 2 * 4 base material count and father object and 4*number of materials
  166.     rge1.size=ksys.chunk.size+pktm.chunk.size+robj.chunk.size+ 3*8 + 2*4 + 4*mesh->materials.numberOfMaterials;    
  167.  
  168.     // number of triangles = sum of each polygon (number of vertices - 2)
  169.     // number of material bodies = sum of each polygon which has a color
  170.     // number of material triangles = sum of each polygon with material (number of vertices - 2)
  171.     ndrei=0,nmatbodies=0,nmattriangles=0;
  172.       if(mesh->polygons.firstNode!=NULL) {                 
  173.         pln=mesh->polygons.firstNode;
  174.         do {
  175.             // we accept only polygons with 3 or more points !
  176.             if (pln->numberOfVertices>=3) {
  177.                 ndrei+=pln->numberOfVertices-2;
  178.                 if (pln->materialNode) {
  179.                     nmatbodies++;
  180.                     nmattriangles+=pln->numberOfVertices-2;
  181.                 }
  182.             }
  183.             pln=pln->next;
  184.         } while (pln!=NULL);
  185.     } 
  186.  
  187.     // the size of the material names = for each material (stringlen(name))
  188.     smaterialnames=0;
  189.     if(mesh->materials.firstNode!=NULL) {
  190.         mat=mesh->materials.firstNode;
  191.         do {
  192.             smaterialnames+=stringlen(mat->name);
  193.             
  194.             mat=mat->next;
  195.         } while(mat!=NULL);
  196.     }
  197.  
  198.     setUBYTEArray(dre2.name,"DRE2",4);
  199.     // size = size of rge1 and its size itself = 8 and rest of this chunk
  200.     // triangles,triangle type,bodies and material bodies
  201.     dre2.size=rge1.size + 8;
  202.     // triangle count size, number of * sizeof(REFTrianlge) and number of for the type flags as UBYTEs
  203.     dre2.size+=4 + ndrei*sizeof(REFTriangle) + ndrei;
  204.     // no bodies, but theyr ULONG size counts too
  205.     dre2.size+=4;
  206.     // size of the matbody count and nmathbodies * 12 and nmattriangles * 4 * 2
  207.     dre2.size+=4 + nmatbodies * 12 + nmattriangles * 4 * 2;
  208.     
  209.     setUBYTEArray(info.chunk.name,"INFO",4);
  210.     info.chunk.size=16;    // fixed size
  211.     info.version=1;        // fixed to 1
  212.     info.revision=2;        // fixed to 2
  213.     // one object and number of materials
  214.     info.nobjects=1+mesh->materials.numberOfMaterials;
  215.     info.chksumpt=0;        // fixed to 0, for future use
  216.     info.chksumobj=0;        // fixed to 0, for future use
  217.     
  218.     setUBYTEArray(form.name,"FORM",4);
  219.     // size = size of info chunk its size = 8 and 4 for REFL and the dre2 chunk size and its size
  220.     // and the size of the materialnames and the number of materials * (sizeof(glanz)+30+28) (gma1 + sur1 + rpic size)
  221.     form.size=info.chunk.size + 12 + dre2.size + 8;
  222.     form.size+=smaterialnames + mesh->materials.numberOfMaterials*(sizeof(glanz)+30+28+16);
  223.  
  224.     setUBYTEArray(gma1.name,"GMA1",4);
  225.  
  226.     setUBYTEArray(rpic.chunk.name,"RPIC",4);
  227.     rpic.chunk.size=8;            // fixed size
  228.     rpic.dx=0,rpic.dy=0;        // no rgb preview
  229.  
  230.     setUBYTEArray(sur1.name,"SUR1",4);
  231.  
  232.     /*
  233.     ** Writing the chunks and theyr dynamic content
  234.     */
  235.     if(FWrite(reffile,&form,sizeof(form),1)!=1) return(RCWRITEDATA);
  236.  
  237.     if(FWrite(reffile,"REFL",1,4)!=4) return(RCWRITEDATA);
  238.     
  239.     if(FWrite(reffile,&info,sizeof(info),1)!=1) return(RCWRITEDATA);
  240.  
  241.     if(FWrite(reffile,&dre2,sizeof(dre2),1)!=1) return(RCWRITEDATA);
  242.     
  243.     if(FWrite(reffile,&rge1,sizeof(rge1),1)!=1) return(RCWRITEDATA);
  244.     
  245.     if(FWrite(reffile,&robj,sizeof(robj),1)!=1) return(RCWRITEDATA);
  246.     if(robj.len) if(FWrite(reffile,mesh->name,1,robj.len)!=robj.len) return(RCWRITEDATA);
  247.  
  248.     if(FWrite(reffile,&ksys,sizeof(ksys),1)!=1) return(RCWRITEDATA);
  249.  
  250.     if(FWrite(reffile,&pktm,sizeof(pktm),1)!=1) return(RCWRITEDATA);
  251.     
  252.     // initialize the buffer state
  253.     bufferstate=0;
  254.  
  255.     // write the points
  256.     // this is a futil test but anyway
  257.     if(mesh->vertices.firstNode!=NULL) {
  258.         ver=mesh->vertices.firstNode;
  259.         do {
  260.             TOCLVertex v=ver->vertex;
  261.  
  262.             vbuffer[bufferstate].x=v.x;
  263.             vbuffer[bufferstate].y=v.y;
  264.             vbuffer[bufferstate].z=v.z;
  265.  
  266.             // increment the bufferstate and 
  267.             // check if the buffer is full and write and initialize it
  268.             if (++bufferstate==Ci_BUFFERS) {
  269.                 if(FWrite(reffile,&vbuffer,Ci_BUFFERS*sizeof(REFVector),1)!=1) return(RCWRITEDATA);
  270.                 bufferstate=0;
  271.             }
  272.                 
  273.             ver=ver->next;
  274.         } while(ver!=NULL);
  275.         
  276.         // write the rest of the buffer if there is any
  277.         if (bufferstate!=0) {
  278.             if(FWrite(reffile,&vbuffer,bufferstate*sizeof(REFVector),1)!=1) return(RCWRITEDATA);
  279.             bufferstate=0;
  280.         }            
  281.     }
  282.  
  283.     // number of materials and theyr indexes
  284.     l=mesh->materials.numberOfMaterials;
  285.     if(FWrite(reffile,&l,sizeof(l),1)!=1) return(RCWRITEDATA);
  286.  
  287.     for(l=1;l<=mesh->materials.numberOfMaterials;l++) {
  288.         if(FWrite(reffile,&l,sizeof(l),1)!=1) return(RCWRITEDATA);
  289.     }
  290.     
  291.     // no father
  292.     l=-1;
  293.     if(FWrite(reffile,&l,sizeof(l),1)!=1) return(RCWRITEDATA);
  294.     
  295.     // triangles
  296.     if(FWrite(reffile,&ndrei,sizeof(ndrei),1)!=1) return(RCWRITEDATA);
  297.     // only if there are any triangles, write them and theyr type flag
  298.     if(ndrei) {
  299.  
  300.         // initialize the buffer state
  301.         bufferstate=0;
  302.  
  303.         // first the triangles
  304.             pln=mesh->polygons.firstNode;
  305.         do {                                
  306.             // only if there are 3 or more points in the polygon
  307.             if(pln->numberOfVertices>=3) {
  308.                 plv1=pln->firstNode;
  309.             
  310.                 plvi=plv1;
  311.                 do {    
  312.                     plv2=plvi->next;
  313.                     plv3=plv2->next;
  314.                 
  315.                     tbuffer[bufferstate].p=plv1->vertexNode->index-1;
  316.                     tbuffer[bufferstate].q=plv2->vertexNode->index-1;
  317.                     tbuffer[bufferstate].r=plv3->vertexNode->index-1;
  318.  
  319.                     // check if the buffer is full and write and initialize it
  320.                     if (++bufferstate==Ci_BUFFERS) {
  321.                         if(FWrite(reffile,&tbuffer,Ci_BUFFERS*sizeof(REFTriangle),1)!=1) return(RCWRITEDATA);
  322.                         bufferstate=0;
  323.                     }
  324.                 
  325.                     plvi=plvi->next;
  326.                 } while(plv3->next!=NULL);    
  327.                     
  328.                 // write the rest of the buffer if there is any
  329.                 if (bufferstate!=0) {
  330.                     if(FWrite(reffile,&tbuffer,bufferstate*sizeof(REFTriangle),1)!=1) return(RCWRITEDATA);
  331.                     bufferstate=0;
  332.                 }
  333.             }
  334.             pln=pln->next;
  335.         } while(pln!=NULL);
  336.         
  337.         // now the flags
  338.         for(i=0;i<ndrei;i++) {
  339.             bbuffer[bufferstate++]=0;    // fixed to a flat shaded triangle
  340.             
  341.             // check if the buffer is full and write and initialize it
  342.             if (bufferstate==Ci_BUFFERS) {
  343.                 if(FWrite(reffile,&bbuffer,Ci_BUFFERS,1)!=1) return(RCWRITEDATA);
  344.                 bufferstate=0;
  345.             }
  346.         }
  347.         // write the rest of the buffer if there is any
  348.         if (bufferstate!=0) {
  349.             if(FWrite(reffile,&bbuffer,bufferstate,1)!=1) return(RCWRITEDATA);
  350.             bufferstate=0;
  351.         }
  352.     }
  353.  
  354.     // we dont use bodies
  355.     l=0;
  356.     if(FWrite(reffile,&l,sizeof(l),1)!=1) return(RCWRITEDATA);
  357.  
  358.     // material bodies
  359.     if(FWrite(reffile,&nmatbodies,sizeof(nmatbodies),1)!=1) return(RCWRITEDATA);
  360.     // if there are any material bodies, write them down
  361.     if(nmatbodies) {
  362.         ULONG tindex;
  363.  
  364.         // initialize the buffer state
  365.         bufferstate=0;
  366.         
  367.         // initilaize the triangle index, first = 0
  368.         tindex=0;
  369.  
  370.           if(mesh->polygons.firstNode!=NULL) {
  371.             pln=mesh->polygons.firstNode;
  372.             do {
  373.                 // we accept only polygons with 3 or more points and which have a material assigned !
  374.                 if (pln->numberOfVertices>=3 && pln->materialNode) {
  375.                     // write the number of triangles in this list = 2 * number of triangles (both sides)
  376.                     l=(pln->numberOfVertices-2)*2;
  377.                     if(FWrite(reffile,&l,sizeof(l),1)!=1) return(RCWRITEDATA);
  378.                   
  379.                       // write the triangle / material list for this polygon
  380.                     for(i=0;i<(pln->numberOfVertices-2);i++) {
  381.                       
  382.                         // each triangle has to be written twice, for both sides
  383.                         lbuffer[bufferstate++]=tindex;
  384.                         lbuffer[bufferstate++]=tindex++;
  385.  
  386.                         // check if the buffer is full and write and initialize it
  387.                         if (bufferstate==Ci_BUFFERS) {
  388.                             if(FWrite(reffile,&lbuffer,Ci_BUFFERS*sizeof(ULONG),1)!=1) return(RCWRITEDATA);
  389.                             bufferstate=0;
  390.                         }                        
  391.                     }
  392.  
  393.                     // write the rest of the buffer if there is any
  394.                     if (bufferstate!=0) {
  395.                         if(FWrite(reffile,&lbuffer,bufferstate*sizeof(ULONG),1)!=1) return(RCWRITEDATA);
  396.                         bufferstate=0;
  397.                     }
  398.  
  399.                     l=0; // fix as it is a material
  400.                     if(FWrite(reffile,&l,sizeof(l),1)!=1) return(RCWRITEDATA);
  401.                     
  402.                     // material index = material index in this file !
  403.                     l=pln->materialNode->index;
  404.                     if(FWrite(reffile,&l,sizeof(l),1)!=1) return(RCWRITEDATA);
  405.                 }
  406.                 pln=pln->next;
  407.             } while (pln!=NULL);
  408.         } 
  409.     }
  410.  
  411.     // writing down all materials
  412.     if(mesh->materials.firstNode!=NULL) {
  413.         REFVector    color;
  414.         FLOAT f;
  415.  
  416.         /* The diffuse color */
  417.         mat=mesh->materials.firstNode;
  418.         do {
  419.             TOCLColor col=mat->diffuseColor;
  420.             color.x=col.r,color.y=col.g,color.z=col.b;
  421.             color.x/=255,color.y/=255,color.z/=255;
  422.  
  423.             robj.len=stringlen(mat->name);
  424.             // size = 2 for the len field and the len value itselfs
  425.             robj.chunk.size=2+robj.len;
  426.  
  427.             // size = size of robj and its size self and the size of the vector
  428.             // and the rpic size and its size
  429.             gma1.size=robj.chunk.size+8+sizeof(REFVector)+rpic.chunk.size+8;
  430.  
  431.             // size = size of gma1 and its size and 5 * 4 (floats) and sizeof(glanz)
  432.             sur1.size=gma1.size + 8 + 5*4 + sizeof(glanz);
  433.  
  434.             if(FWrite(reffile,&sur1,sizeof(sur1),1)!=1) return(RCWRITEDATA);
  435.  
  436.             if(FWrite(reffile,&gma1,sizeof(gma1),1)!=1) return(RCWRITEDATA);
  437.             
  438.             if(FWrite(reffile,&robj,sizeof(robj),1)!=1) return(RCWRITEDATA);
  439.             if(robj.len) if(FWrite(reffile,mat->name,1,robj.len)!=robj.len) return(RCWRITEDATA);
  440.             
  441.             if(FWrite(reffile,&color,sizeof(color),1)!=1) return(RCWRITEDATA);
  442.             
  443.             if(FWrite(reffile,&rpic,sizeof(rpic),1)!=1) return(RCWRITEDATA);
  444.             
  445.             // diffuse reflection
  446.             f=1-mat->transparency-mat->shininess;
  447.             if(FWrite(reffile,&f,sizeof(f),1)!=1) return(RCWRITEDATA);
  448.  
  449.             // reflections
  450.             f=0;
  451.             if(FWrite(reffile,&f,sizeof(f),1)!=1) return(RCWRITEDATA);
  452.  
  453.             // transparency
  454.             f=mat->transparency;
  455.             if(FWrite(reffile,&f,sizeof(f),1)!=1) return(RCWRITEDATA);
  456.  
  457.             // shininess
  458.             f=mat->shininess;
  459.             if(FWrite(reffile,&f,sizeof(f),1)!=1) return(RCWRITEDATA);
  460.  
  461.             // index of refraction
  462.             f=0;
  463.             if(FWrite(reffile,&f,sizeof(f),1)!=1) return(RCWRITEDATA);
  464.  
  465.             // glanzlichtkurve including its size
  466.             if(FWrite(reffile,&glanz,sizeof(glanz),1)!=1) return(RCWRITEDATA);
  467.  
  468.             mat=mat->next;
  469.         } while(mat!=NULL);
  470.     }
  471.  
  472.     return(RCNOERROR);
  473. }
  474.  
  475. /************************* End of file ******************************/
  476.